#pragma once

#include "Typelist.h"
#include "Functor.h"
#include <string>
#include <climits>
template<class T>
class CTinyTimerID
{
private:
	CTinyTimerID(void){};
	~CTinyTimerID(void){};
};

template<>
class CTinyTimerID<long>
{
public:
	CTinyTimerID(void){ generateTimerID();}
	~CTinyTimerID(){}
private:
	static long m_ID;
private:
	void generateTimerID()
	{
		m_ID = (*getStaticFlag())++;
		return;
	}
	static long* getStaticFlag()
	{
		static long refFlag = 0;
		//reset value if exceed the value range.
		if(refFlag>LONG_MAX-2||refFlag<0)
			refFlag = 0;
		return &refFlag;
	}

public:

	long getID(void)
	{
		return m_ID;
	}
};
template<>
class CTinyTimerID<std::string>
{
public:
	CTinyTimerID(void){ generateTimerID(); }
	~CTinyTimerID(){}
private:
	void generateTimerID()
	{
		long  t1=GetTickCount();
		char idstr[65];
		long id = (*getStaticFlag())++;
		_itoa_s(t1,idstr,65,10);
		m_strID = idstr;
		_itoa_s(id,idstr,65,10);
		m_strID+=":"+std::string(idstr);

		return;
	}
	static long* getStaticFlag()
	{
		static long refFlag = 0;
		//reset value if exceed the value range.
		if(refFlag>LONG_MAX-2||refFlag<0)
			refFlag = 0;
		return &refFlag;
	}

	std::string m_strID;

public:

	std::string getID(void) const
	{
		return m_strID;
	}
};


template < class T >
class CTinyTimer
{
public:
	CTinyTimer(void);
	CTinyTimer(T& TimerID,Loki::Functor<void,LOKI_TYPELIST_1( T& ) >* pFunc,long interval = 0,bool active = false):
	  m_isAlive(active),
	  m_interval(interval),
	  m_TimerID(TimerID),
	  m_pFunctor(pFunc)
	{

	}
	~CTinyTimer(void);

	bool start(long interval = 0)
	{
		if(interval > 0)
			m_interval = interval;
		m_isAlive = true;
		m_during = m_interval;
		return 0;
	}

	bool stop(void)
	{
		m_isAlive = false;
		return 0;
	}

	bool countDown(long interval)
	{
		if(m_interval<=0)
			return false;

		if(!m_isAlive)
			return false;

		m_during -= interval;
		if(m_during<=0)
		{
			//Call callback function
			if(m_pFunctor!=NULL)
			{
				(*m_pFunctor)( m_TimerID );
			}
			m_during = m_interval;
		}
		return true;
	}
private:
	Loki::Functor<void,LOKI_TYPELIST_1( T& ) >* m_pFunctor;
	bool m_isAlive;
	T& m_TimerID;
	long m_interval;
	long m_during;
public:

	bool isAlive(void)
	{
		return m_isAlive;
	}
};